from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

# 导入又拍云
import upyun

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F 

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User

# 导入redis库
import redis

#定义地址和端口
host = '127.0.0.1'
port = 6379

#建立redis连接
r = redis.Redis(host=host,port=port)


# 导入序列化类
from myapp.myser import *



# 
class GetUsers(View):
    def get(self,request):

        users = User.objects.filter().values("id","username")

        users = list(users)

        # myusers = json.loads(serialize('json',users,ensure_ascii=False))

        return JsonResponse(users,safe=False,json_dumps_params={'ensure_ascii':False})

# 轮播图后台接口
class GetCarousel(APIView):
    def get(self,request):

        # 读库
        carousels = Carousel.objects.all()

        # 序列化操作
        carousels_ser = CarouselSer(carousels,many=True)

        return Response(carousels_ser.data)

# 插入幻灯片
class InsertCar(APIView):
    def get(self,request):

        # 接收参数
        name = request.GET.get('name','null')
        src = request.GET.get('src','null')
        img = request.GET.get('img','null')


        # 排重
        caro = Carousel.objects.filter(name=name).first()

        if caro:
            res = {}
            res['code'] = 405
            res['message'] = '该活动已存在'
            return Response(res)

        # 入库
        car = Carousel(name=name, src=src,img=img)
        car.save()

        res = {}
        res['code'] = 200
        res['message'] = '注册成功'

        return Response(res)

    
# 删除幻灯片
class DeCar(APIView):
    def post(self,request):
        id = request.data['id']
        Carousel.objects.filter(id=id).delete()
        return Response({
            'code': 200
        })



# 修改幻灯片
class UpCar(APIView):
    def get(self,request):
        id = request.GET.get('id')
        name = request.GET.get('name')
        src = request.GET.get('src')
        img = request.GET.get('img')

        Carousel.objects.filter(id=id).update(
            name=name,
            src=src,
            img=img
                                          )
        return Response({
            'code': 200
        })




# 定义七牛云token
from qiniu import Auth

class QiNiu(APIView):
    def get(self,request):

        # 声明认证对象
        q = Auth('BNJACqPq8b6i9Ljsp5pSc2y8gPrlh1qtKfvaX9-i','4UmG7vDrwM9Hs5DZftTlGXySuFl27P6yhzSmtQXo')

        # 获取token
        token = q.upload_token('1907bb')

        return Response({
            'token':token
        })







import cv2

# 定义文件上传通用类
class UploadFile(APIView):
    def post(self,request):
        # 接收参数
        myfile = request.FILES.get('file')
        
        uid = request.POST.get('uid',None)
        print(uid)
        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT,'',myfile.name),'wb')
        # 写入
        for chunk in myfile.chunks():
            f.write(chunk)
        f.close()
        # 修改头像地址
        user = User.objects.get(id=int(uid))
        user.img = myfile.name
        user.save()
        # 设置图片打开路径
        imgpath = './static/upload/' + myfile.name
        # 打开图片
        im = Image.open(UPLOAD_ROOT+'/'+ myfile.name)
        # 生成画笔对象
        draw = ImageDraw.Draw(im)
        # 字体
        font = ImageFont.truetype(font='C:\\Windows\\Fonts\\simkai.ttf', size=50)
        # 绘制图片
        draw.text((50, 200), '加油', fill=(76, 234, 124, 180), font=font)
        # 图像压缩
        # 读图
        img = cv2.imread(UPLOAD_ROOT+'/'+ myfile.name)
        # 压缩操作
        cv2.imwrite(UPLOAD_ROOT+'/'+myfile.name,img,[cv2.IMWRITE_JPEG_QUALITY,50])
        # # 查看图片
        # im.show()
        # 存储图片
        im.save(UPLOAD_ROOT+'/'+ myfile.name)
    

        # 返回文件名
        return Response({
            'filename':myfile.name
        })



from django.utils.deprecation import MiddlewareMixin

# 自定义中间件类
class MyMiddleware(MiddlewareMixin):
    # 请求之前
    def process_request(self,request):

        print('中间件')

        if request.path_info.startswith("/userinfo"):

            return HttpResponse(json.dumps({'message':"您篡改了uid"},ensure_ascii=False,indent=4),content_type="application/json")
#         uid = request.GET.get('uid')
#         clinet_jwt = request.GET.get('jwt',None)
    
#         decode_jwt = jwt.decode(clinet_jwt, 'tsk123', algorithms=['HS256'])
#         if decode_jwt['uid'] != str(uid):
    
#             return HttpResponse('你没有JWT令牌')
        # pass
        

    # 模板渲染之前
    def process_view(self,request,view_func,view_args,view_kwargs):
        pass

    def process_exception(self,request,exception):
        pass
    # 请求之后
    def process_response(self,request,response):
        return response




# 定义权限检测装饰器
def my_decorator(func):
    def wrapper(request,*args,**kwargs):

        # 接收参数
        uid = request.GET.get('uid',None)

        myjwt = request.GET.get('jwt')

        print(myjwt)

        # 验证用户合法性
        decode_jwt = jwt.decode(myjwt,'tsk123',algorithms=['HS256'])

        # 进行比对
        if int(uid) != int(decode_jwt['uid']):
            
            return Response({
                'code':401,
                'message':'您的密钥无权限'
            })


        return func(request,*args,**kwargs)
    return wrapper

# 导入装饰器包
from django.utils.decorators import method_decorator

# 获取用户信息接口
class UserInfo(APIView):

    @method_decorator(my_decorator)
    def get(self,request):

        # 接收参数
        uid = request.GET.get('uid',None)

        # 查询数据库
        user = User.objects.get(id=int(uid))

        if user.img =="":
            user.img = "sina.png"

        #返回
        return Response({
            'img':user.img,
            'phone':user.phone
        })


# 导包
import upyun
# 又拍云
class UpYun(APIView):
    def post(self,request):

        # 获取文件
        file = request.FILES.get('file')
        # 新建又拍云实例
        up = upyun.UpYun('1907b','tt1216124438','ahrPZf37Jw6KXBtRxOoF1RrEwKmnapNg')
        # 声明头部信息
        headers = {'x-gmkerl-rotate':'auto'}
        # 上传图片
        for chunk in file.chunks():
            res = up.put('/' + file.name,chunk,checksum=True,headers=headers)

                    #返回结果
        return Response({'filename':file.name})


# 创建目录
class UpYunPro(View):            
    def get(self, request):
        crdir = request.GET.get('crdir')
        up = upyun.UpYun('1907b', username='tt1216124438', password='ahrPZf37Jw6KXBtRxOoF1RrEwKmnapNg')
        up.mkdir(crdir + '/')
        return HttpResponse(json.dumps({
            'code': 200
            }))






# 新浪微博回调方法
def wb_back(request):

    # 接收参数
    code = request.GET.get('code',None)

    # 定义token接口地址
    url = "https://api.weibo.com/oauth2/access_token"
    # 定义参数
    re = requests.post(url,data={
        'client_id':'3249062725',
        'client_secret':'544244413e2dc845fddd5a9b5ecf8170',
        'grant_type':'authorization_code',
        'code':code,
        'redirect_uri':'http://127.0.0.1:8000/md_admin/weibo'
    })
    # print(re.json())
    # 换取新浪微博用户信息
    res = requests.get('https://api.weibo.com/2/users/show.json',params={'access_token':re.json()['access_token'],'uid':re.json()['uid']})
    # print(res.json())

    sina_id = ''
    user_id = ''
    # 判断是否用新浪微博登陆过
    user = User.objects.filter(username=str(res.json()['name'])).first()
    if user:
        # 代表曾经用该账号登陆过
        sina_id = user.username
        user_id = user.id
    else:
        # 首次登录 入库新浪微博账号
        user = User(username=str(res.json()['name']),password='')
        user.save()
        user = User.objects.filter(username=str(res.json()['name'])).first()
        sina_id = user.username
        user_id = user.id
    print(sina_id,user_id)
    # 重定向
    return redirect("http://localhost:8080?sina_id="+str(sina_id)+"&uid="+str(user_id))
    # return HttpResponse('回调成功')

import base64
import hmac
from hashlib import sha256
import urllib
import time
from urllib import parse


# 钉钉第三方登录
def ding_back(request):
    # 接收参数
    code = request.GET.get('code',None)

    t = time.time()

    timestamp = str((int(round(t * 1000))))

    appSecret = 'rDsIHGCcvj8wgd12KCafOUEwA2Vm8Uh9uhnvhvohwxwfXxGkwd86DLpR3d7n0McG'

        # 构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'),digestmod=sha256).digest())

        # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type':'application/json'}

    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoas0flvw1koxnmk1fa",data=json.dumps(payload), headers=headers)


    res_dict = json.loads(res.text)
    print(res_dict)
    # return HttpResponse(res.text)
    ding_nick = res_dict['user_info']['nick']


    user = User.objects.filter(username=ding_nick).first()

    user_id = ''

    if user:
        ding_nick = user.username
        user_id = user.id

    else:
        # 手动创建账号
        user = User(username=str(ding_nick),password='')
        user.save()

        # 查询一下刚刚入库的新账号id
        user = User.objects.filter(username=str(ding_nick)).first()
        user_id = user.id

        print(user_id)

    return redirect("http://localhost:8080?ding_nick=" + str(ding_nick)+"&uid="+str(user_id))
    




      


#修改密码
class UpdatePass(APIView):
    def get(self, request):
        # 获取用户信息
        uid = request.GET.get('uid')
        password = request.GET.get('password')

        # 查询用户是否存在
        user = User.objects.filter(id=uid).first()
        print(request.GET.get('uid'))
        print(request.GET.get('password'))

        if user:
            user.password = make_password(password)
            user.save()

            return Response({
                'code': 200,
                'data': '修改成功'
            })

        return Response({
            'code': 405,
            'data': '修改失败'
        })



#自定义图片验证码  使用view APIView 返回json  这是返回图片的 HttpResponse
class MyCode(View):
    # 定义rgb随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R,G,B)
    # 定义图片视图
    def get(self,request):
        # 画布
        img_size = (120,50)
        # 定义图片对象
        image = Image.new('RGB',img_size,'white')
        # 定义画笔
        draw = ImageDraw.Draw(image,'RGB')
        # 定义内容
        source = '123456qweasdzxc'
        # 接收容器
        code_str = ''
        # 定义字体 simsun.ttc简体中文
        my_font = ImageFont.truetype(font="c:\\Windows\\Fonts\\Arial.ttf",size=15)
        for i in range(4):
            # 获取字母颜色
            text_color = self.get_random_color()
            # 获取随机下标
            tmp_num = random.randrange(len(source))
            # 随机字符串
            random_str = source[tmp_num]
            # 装入容器
            code_str += random_str
            # 绘制字符串
            draw.text((10+30*i,20),random_str,text_color,font=my_font)
        # 获取缓存区
        buf = io.BytesIO()
        # 将临时图片保存到缓冲
        image.save(buf,'png')
        # 保存随机码
        r.set('code',code_str)
        # # 保存session  不建议使用 容易消耗数据库内存
        # request.session['code'] = code_str


        return HttpResponse(buf.getvalue(),'image/png')


# md5加密方法
def make_password(mypass):

    # 生成md5对象
    md5 = hashlib.md5()

    # 转码操作
    mypass_utf8 = str(mypass).encode(encoding="utf-8")

    # 加密操作
    md5.update(mypass_utf8)

    # 返回密文
    return md5.hexdigest()

# 登录接口
class Login(APIView):
    def get(self,request):
        # 接收参数
        username = request.GET.get('username',None)
        password = request.GET.get('password',None)
        code = request.GET.get('code',None)

        # 使用redis判断用户输入错误次数
        # 用列表形式将用户名存进redis库中
        r.lpush(username,username)
        r.expire(username,30)

        # 判断列表元素
        if r.llen(username) > 5:
            return Response({
                'code': 400,
                'message': '错误次数太多，请稍候'
            })

         # 获取验证码
        redis_code = r.get('code')
        print(redis_code)
        # # 从session取值
        # session_code = request.session.get('code',None)
        # print(session_code)
        
        # 转码
        redis_code = redis_code.decode('utf-8')
        print(redis_code)
        # 判断验证码是否正确
        if code != redis_code:
            res = {}
            res['code'] = 405
            res['message'] = '验证码错误'
            return Response(res)

        # 查询数据 
        user = User.objects.filter(Q(username=username) | Q(phone=username),password=make_password(password)).first()
        if user:
            
            # 生成用户token
            # 生成jwt
            encode_jwt = jwt.encode({'uid':user.id},'tsk123',algorithm='HS256')

            #转码 强转
            encode_str = str(encode_jwt,'utf-8')

            return Response({
                'code': 200,
                'message': '登录成功',
                'uid': user.id,
                'username':user.username,
                'jwt': encode_str
            })
        else:
            return Response({
                'code': 403,
                'message': '用户名或密码错误'
            })
        



# 注册接口
class Register(APIView):
    def get(self,request):

        # 接收参数
        username = request.GET.get('username',None)
        password = request.GET.get('password',None)

        # 排重
        user = User.objects.filter(username=username).first()

        if user:
            return Response({
                'code': 400,
                'message':'用户名重复'
            })
        # 入库操作
        user = User(username=username,password=make_password(password))
        # 保存结果
        user.save()

        return Response({
            'code':200,
            'message':'注册成功'
        })
            
    # def post(self,request):

    #     # 接收参数
    #     username = request.POST.get('username',None)
    #     password = request.POST.get('password',None)

    #     # 排重
    #     user = User.objects.filter(username=username).first()

    #     if user:
    #         return Response({
    #             'code': 400,
    #             'message':'用户名重复'
    #         })
    #     # 入库操作
    #     user = User(username=username,password=make_password(password))
    #     # 保存结果
    #     user.save()

    #     return Response({
    #         'code':200,
    #         'message':'注册成功'
    #     })














